//*************************************************************************************
// Helper functions for bitboard operations
//*************************************************************************************

#pragma once

#include "Common.h"

extern uint32 RevWord[65536];

// initializes the internal variables for the fast bitboard operations
void InitBool();

// 32-bit routines
int LSB(uint32 x);
int MSB(uint32 x);
int RecBitCount(uint32 n);
int BitCount(uint32 n);
uint32 Revert(uint32 n);

// 64-bit routines
int LSB64(uint64 x);
int MSB64(uint64 x);
int BitCount64(uint64 n);

// reverts bits in the number
// maximum 64-bit version for the variable bitsize - 10x10 checkersboard takes 50 bits
template<int BitSize>
uint64 Revert64(uint64 n)
{
	uint64 result = (RevWord[HiDWordHiWord(n)] + (RevWord[HiDWordLoWord(n)]<<16) 
				+ (((uint64)RevWord[HiWord(n)])<<32) + (((uint64)RevWord[LoWord(n)])<<48));
	return result >> (64 - BitSize);
}



// template versions - switching between various bitboard sizes
/////////////////////////////////////////////////////////////////////////////////////////////////////


// LSB - the least significant bit
template<typename BB> int LSBxx(typename BB::value_type x)
{
	assert(false);
}

template<> int LSBxx<BitBoard>(typename BitBoard::value_type x);
template<> int LSBxx<BitBoard64>(typename BitBoard64::value_type x);


// MSB - the most significant bit
template<typename BB> int MSBxx(typename BB::value_type x)
{
	assert(false);
}

template<> int MSBxx<BitBoard>(typename BitBoard::value_type x);
template<> int MSBxx<BitBoard64>(typename BitBoard64::value_type x);


// The number of bits 
template<typename BB>  int BitCountXX(typename BB::value_type x)
{
	assert(false);
}

template<> int BitCountXX<BitBoard>(typename BitBoard::value_type x);
template<> int BitCountXX<BitBoard64>(typename BitBoard64::value_type x);


// Revert - reversing the bits in the UINT32 or UINT64
template<typename BB> typename BB::value_type RevertXX(typename BB::value_type x)
{
	assert(false);
}

template<> typename BitBoard::value_type RevertXX<BitBoard>(typename BitBoard::value_type x);
template<> typename BitBoard64::value_type RevertXX<BitBoard64>(typename BitBoard64::value_type x);
